﻿using System;
using System.Windows;
using System.Windows.Markup;
using Pfz.Factoring;

namespace Pfz.WpfControls
{
	/// <summary>
	/// Control that shows the registered editor for a data-type.
	/// </summary>
	[ContentProperty("DataContext")]
	public sealed class EditorControl:
		ContentCreatorControl
	{
		/// <summary>
		/// Initializes the EditorControl class.
		/// </summary>
		static EditorControl()
		{
			DataContextProperty.OverrideMetadata
			(
				 typeof(EditorControl),
				 new FrameworkPropertyMetadata
				 (
					_DataContextChanged
				 )
			);
		}
		private static void _DataContextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			var control = (EditorControl)sender;
			control.OnDataContextChanged(args.NewValue);
		}

		private Type _dataType;
		/// <summary>
		/// Gets or sets the DataType of this control.
		/// </summary>
		public Type DataType
		{
			get
			{
				return _dataType;
			}
			set
			{
				if (value == null)
				{
					_dataType = null;
					Content = null;
					return;
				}

				var dataContext = DataContext;
				if (dataContext != null && !value.IsAssignableFrom(dataContext.GetType()))
					DataContext = null;

				_dataType = value;
				InvalidateContent();
			}
		}

		/// <summary>
		/// Gets the Editor used by this control.
		/// </summary>
		public IEditor Editor { get; private set; }

		private void OnDataContextChanged(object dataContext)
		{
			if (dataContext == null)
				Content = null;
			else
				InvalidateContent();
		}

		/// <summary>
		/// Creates the Editor for the appropriate datatype.
		/// </summary>
		protected override void OnCreateContent()
		{
			base.OnCreateContent();

			var dataContext = DataContext;
			var dataType = _dataType;

			if (dataType == null)
			{
				if (dataContext == null)
				{
					Content = null;
					return;
				}

				dataType = dataContext.GetType();
			}
			else
			{
				if (dataContext != null && !dataType.IsAssignableFrom(dataContext.GetType()))
					dataContext = null;
			}

			var factory = Factories<IEditor>.TryCreateFactory(dataType);
			if (factory == null)
			{
				Content = "Can't find editor for data type " + dataType.FullName + ".";
				return;
			}

			var editor = factory.Create();
			editor.Record = dataContext;
			Editor = editor;
			Content = editor;
		}
	}
}
